package com.qf.kele02.service.impl;

import cn.hutool.core.io.file.FileAppender;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import com.qf.kele02.dao.UserDao;
import com.qf.kele02.entity.User;
import com.qf.kele02.service.UserSevice;
import com.qf.kele02.utils.Constants;
import com.qf.kele02.vo.ResultVo;
import com.qf.kele02.vo.TableVo;
import com.qf.kele02.vo.UserVo;
import com.qf.kelespringbootstarter.utils.FileAppendUtils;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.ParseException;
import java.util.*;
import java.util.function.Function;

@Service
@Slf4j
public class UserSeviceImpl implements UserSevice {

	@Autowired
	private UserDao userDao;

	@Autowired
	private FileAppendUtils< User > fileAppenderUtils;

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public User getUser( Integer id ) {

		return userDao.getUserById( id );

	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public User login( String username,String password ) {
		log.debug( "userservice查询用户收到的参数为username={},passowrd={}",username,password );

		//1. 根据用户名查询用户
		User user=userDao.getUserByName( username );

		if(user==null) {
			return null;
		}

		//2. 比对数据库中的密码和登录表单中传递的密码是否一致

		// 把用户传递的password进行md5转换
		final String md5Password=DigestUtil.md5Hex( password );

		if(md5Password.equals( user.getPassword( ) )) {
			return user;
		}else {
			return null;
		}

	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public ResultVo regist( UserVo userVo,String realPath ) throws IOException {

		log.debug( "开始保存头像文" );
		final MultipartFile file1=userVo.getFile1( );
		//1. 生成一个唯一的文件名 ： 唯一前缀 + 原始文件名
		final String prefix=UUID.randomUUID( ).toString( );

		final String originalFilename=file1.getOriginalFilename( );
		final String extension=FilenameUtils.getExtension( originalFilename );
		final String finalFileName=prefix+"."+extension;

		final String finalFilePath=realPath+File.separator+finalFileName;

		// 判断 realPath 对应的目录是否存在，如果不存在则创建
		final File dir=new File( realPath );
		if(!dir.exists( )) {
			dir.mkdirs( );
		}

		// 存文件
		file1.transferTo( new File( finalFilePath ) );
		log.debug( "保存头像文件成功:finalFilePath={}",finalFilePath );

		log.debug( "保存用户的注册信息到数据库中" );
		// userVo  ----- >  user
		final User user=new User( );

		// 从一个对象中拷贝相同属性到另一个对象中
		BeanUtils.copyProperties( userVo,user );


		// 补全剩下的属性
		user.setName( userVo.getUsername( ) );
		user.setRegistTime( new Date( ) );
		user.setPhotopath( finalFileName );

		// 处理密码加密
//        user.setPassword();
		final String md5password=DigestUtil.md5Hex( userVo.getPassword( ) );
		user.setPassword( md5password );
		log.debug( "保存的用户信息为:user={}",user );
		userDao.insertUser( user );
		log.debug( "保存用户成功" );
		return new ResultVo( Constants.SUCCESS_CODE,"注册用户成功" );
	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public ResultVo checkUsername( String username ) {

		final User user=userDao.getUserByName( username );

		if(user==null) {
			// 用户名不存在
			return new ResultVo( Constants.SUCCESS_CODE,"用户名不存在" );
		}else {
			return new ResultVo( Constants.FAIL_CODE,"用户名已经存在了" );
		}

	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public TableVo getAllUserByPage( Integer page,Integer limit ) {

		// 查询user总条数
		Integer count=userDao.selectCount( );

		// 查询当前页的用户数据

		final Integer start=(page-1)*limit;  // 计算分页的起始行号

		List< User > users=userDao.selectUserByPage( start,limit );


		final TableVo< User > userTableVo=new TableVo<>( );

		userTableVo.setCode( 0 );
		userTableVo.setMsg( "OK" );
		userTableVo.setData( users );
		userTableVo.setCount( count );

		return userTableVo;
	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public User restoreUser( String username,String md5password ) {
		log.debug( "userservice查询用户收到的参数为username={},md5password={}",username,md5password );

		//1. 根据用户名查询用户
		User user=userDao.getUserByName( username );

		if(user==null) {
			return null;
		}

		//2. 比对数据库中的密码和登录表单中传递的密码是否一致

		if(md5password.equals( user.getPassword( ) )) {
			return user;
		}else {
			return null;
		}
	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public TableVo getUserByPagehelper( Integer page,Integer limit ) {

		PageHelper.startPage( page,limit );
		final List< User > users=userDao.getAllUser( );
		final PageInfo< User > pageInfo=new PageInfo<>( users );
		final long count=pageInfo.getTotal( );

		return TableVo.ok( (int) count,users );
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public ResultVo addUser( User user ) {

		// 要把密码进行md5处理
		final String password=user.getPassword( );

		final String md5Password=DigestUtil.md5Hex( password );

		user.setPassword( md5Password );

		user.setRegistTime( new Date( ) );

		final Integer result=userDao.insertUser( user );

		return new ResultVo( Constants.SUCCESS_CODE,"添加用户成功" );

	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public ResultVo deleteUserByIds( List< Integer > ids ) {

		userDao.deleteUserByIds( ids );

		return new ResultVo( Constants.SUCCESS_CODE,"删除用户成功" );
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public ResultVo updateUser( User user ) {

		// 对于密码的处理
		final String password=user.getPassword( );

		// 查询数据库中的用户信息
		final User dbuser=userDao.getUserById( user.getId( ) );

		final String dbpassword=dbuser.getPassword( );

		if(!dbpassword.equals( password )) {
			log.debug( "用户修改了密码，重新进行md5预算" );
			final String md5password=DigestUtil.md5Hex( password );
			user.setPassword( md5password );
		}

		userDao.updateUser( user );

		return new ResultVo( Constants.SUCCESS_CODE,"修改用户成功" );
	}

	@Transactional(propagation=Propagation.SUPPORTS)
	@Override
	public TableVo< User > getUsersByContdition( Integer page,Integer limit,UserVo userVo ) {

		PageHelper.startPage( page,limit );
		List< User > data=userDao.getUsersByContdition( userVo );
		final PageInfo< User > pageInfo=new PageInfo<>( data );
		final long total=pageInfo.getTotal( );

		return TableVo.ok( (int) total,data );
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public String export( ) throws IllegalAccessException, ClassNotFoundException {

		//生成一个文件追加器
		int page=1;
		String realpath="F:\\";
		String name=UUID.randomUUID( ).toString( ).substring( 0,7 )+".csv";
		File file=new File( realpath );
		if(!file.exists( )) {
			file.mkdirs( );
		}
		File finallyFile=new File( realpath+File.separator+name );
		FileAppender fileAppender=new FileAppender( finallyFile,8,true );

		PageHelper.startPage( page,2 );
		List< User > allUser=userDao.getAllUser( );

		User user=new User( );
		user.setId( 100 );
		user.setName( "zhangsan" );
		List< User > users=Arrays.asList( user );
		//调用工具类来实现
		fileAppenderUtils.getHead( fileAppender,User.class.getCanonicalName( ) );
		fileAppenderUtils.fileAppend( users,fileAppender,User.class.getCanonicalName( ) );

		//使用工具类的批量追加
		while(allUser.size( )>0) {
			++page;
			PageHelper.startPage( page,2 );
			allUser=userDao.getAllUser( );

			if(allUser.size( )>0) {
				fileAppenderUtils.fileAppend( allUser,fileAppender,User.class.getCanonicalName( ) );
			}else {
				break;
			}
		}

		return name;
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public TableVo< User > insert( MultipartFile source ) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException, ParseException {
		//将收到的文件包装成增强型字符流
		InputStream inputStream=source.getInputStream( );
		BufferedReader ber=new BufferedReader( new InputStreamReader( inputStream ) );

		//去除表头
		fileAppenderUtils.delHead( ber );

		//开始分批读取文件
		List< User > list=fileAppenderUtils.readForTimes( ber,2,User.class.getCanonicalName( ) );

		Integer interger=0;
		//集合为空的时候不添加
		if(list.size( )>0) {
			interger=userDao.insertUsers( list );
		}


		//只要一出现异常立马就不添加，即使止损
		if(interger<=0) {
			//直接返回结果
			return new TableVo<>( Constants.FAIL_CODE,"unsuccessful",interger );
		}
		//循环读取只要集合不为size不为0
		while(list.size( )>0) {
			list=fileAppenderUtils.readForTimes( ber,2,User.class.getCanonicalName( ) );

			//集合为空的时候不添加
			if(list.size( )>0) {
				interger=userDao.insertUsers( list );
			}
			if(interger<=0) {
				//直接返回结果
				return new TableVo<>( Constants.FAIL_CODE,"unsuccessful",interger );
			}
		}


		//释放资源
		inputStream.close( );
		ber.close( );

		//返回结果
		return new TableVo<>( Constants.SUCCESS_CODE,"successful",interger );
	}

	@Override
	public ResultVo deleteHead( ) {
		//这一块可热闹了
		//查询数据库中所有的头像名
		List< String > list=userDao.selectPhotos( );

		//获取相应文件中的所有文件
		File file=new File( Constants.RealPath );


		//开始表演
		File[] files=file.listFiles( );
		for(File file1: files) {
			if(file1.isFile( ) && !list.contains( file1.getName( ) )) {
				file1.delete( );
			}
		}

		return new ResultVo( Constants.SUCCESS_CODE,"successful" );
	}

	@Override
	public boolean saveBatch( Collection< User > entityList,int batchSize ) {
		return false;
	}

	@Override
	public boolean saveOrUpdateBatch( Collection< User > entityList,int batchSize ) {
		return false;
	}

	@Override
	public boolean updateBatchById( Collection< User > entityList,int batchSize ) {
		return false;
	}

	@Override
	public boolean saveOrUpdate( User entity ) {
		return false;
	}

	@Override
	public User getOne( Wrapper< User > queryWrapper,boolean throwEx ) {
		return null;
	}

	@Override
	public Map< String, Object > getMap( Wrapper< User > queryWrapper ) {
		return null;
	}

	@Override
	public < V > V getObj( Wrapper< User > queryWrapper,Function< ? super Object, V > mapper ) {
		return null;
	}

	@Override
	public BaseMapper< User > getBaseMapper( ) {
		return null;
	}

	@Override
	public Class< User > getEntityClass( ) {
		return null;
	}
}
